package it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.ai;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.pawn.Character;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.player.BattlePlayer;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.world.Map;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.EndActionEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.EndMatchEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.EventListener;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.EventManager;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.FinalMovementEventInformation;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.GenericEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.TurnEvent;

public abstract class AutomatedPlayerController implements AI, EventListener {

	  protected BattlePlayer player;
	  protected BattlePlayer enemyPlayer;
	  
	  protected boolean canPlayMove = false;
	  protected boolean mustSkip = false;
	  protected boolean turnUp = false;
	  protected boolean matchOver = false;
	  protected ReentrantLock lock = new ReentrantLock();
	  protected Condition condition = lock.newCondition();
		
		
	  public void init()
	  {
			EventManager.getInstance().addListener(this, new TurnEvent());
			EventManager.getInstance().addListener(this, new EndMatchEvent());
			EventManager.getInstance().addListener(this, new EndActionEvent());
			EventManager.getInstance().addListener(this, new FinalMovementEventInformation(0,0,0,0));
			System.out.println("INIT AI");
	  }
	  
		public AutomatedPlayerController(BattlePlayer aiPlayer, BattlePlayer enemyPlayer) {

//			init();
			this.player = aiPlayer;
		}
		
		
		public AutomatedPlayerController(BattlePlayer enemyPlayer)
		{

//			init();
			this.enemyPlayer = enemyPlayer;
			player = new BattlePlayer();
			player.setNickname("aiPlayer");
		}
		

//		public 
	
	@Override
	public void preStartMatch(Map map) 
	{
		init();
//		System.out.println(map);
	}
	@Override
	public void notify(GenericEvent event) 
	{
		
		if(event.getGUID() == EndActionEvent.GUID)
		{
			if(turnUp) 
			{
				// maybe you killed all enemy characters
				// and you don't have to do anything but wait for EndActionEvent
				if(enemyPlayer.hasAliveCharacters())
					wakeAI();
			}
		}
		else if(event.getGUID() == TurnEvent.GUID)
		{
			TurnEvent turnEvent = (TurnEvent) event;
			System.out.println("TURN EVENT AI CLASS");
			
			if(turnEvent.getNewPlayer().equals(player.getNickname()))
			{
				// Call update method (maybe ai has to set up something before turn starts)
				update();
				
				// It's ai turn: wake it up and allow it to play its moves
				turnUp = true;
				wakeAI();
			
			} 
			else 
			{
				turnUp = false;
				canPlayMove = false;
				// It's human turn: ai cannot play moves
				System.out.println("TURNO HUMAN");
			}

		}
		else if(event.getGUID() == EndMatchEvent.GUID)
		{
			matchOver = true;
			//if match is over, wake up AI to let it exit run() method
				wakeAI();
			//if AI won, it would play a move again, so prevent that by setting
			// this boolean to true
			mustSkip = true;
		
			player.disband();
			player.setCharacters(new LinkedList<Character>());
		}


		
	}

	private void wakeAI() 
	{
		System.out.println("WAKE UP AI");
		lock.lock();
		canPlayMove = true;
		condition.signal();
		lock.unlock();
	}
	
	@Override
	public void run() {
	 
		while(!matchOver) 
		{
			lock.lock();
			while(!canPlayMove) 
			{
			try {
				condition.await();
			} catch (InterruptedException e) 
			{
				e.printStackTrace();
			}
			lock.unlock();
			}
			if(!mustSkip) 
			{
				makeMove();
				canPlayMove = false;
			}
		}
		
//		System.out.println("AI STOPS RUNNING");
	}


	/**
	 * @return the aiPlayer
	 */
	public BattlePlayer getAiPlayer() {
		return player;
	}


	/**
	 * @param aiPlayer the aiPlayer to set
	 */
	public void setAiPlayer(BattlePlayer aiPlayer) {
		this.player = aiPlayer;
	}

	/**
	 * @return the player
	 */
	public BattlePlayer getPlayer() {
		return player;
	}

	/**
	 * @param player the player to set
	 */
	public void setPlayer(BattlePlayer player) {
		this.player = player;
	}
	
}
